﻿//  Copyright (c) 2009 Ray Liang (http://www.dotnetage.com)
//  Dual licensed under the MIT and GPL licenses:
//  http://www.opensource.org/licenses/mit-license.php
//  http://www.gnu.org/licenses/gpl.html
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace DNA.Mvc.jQuery
{
    public static class DropDownTreeExtensions
    {
        private static void WriteNodeRecursive(NodeUIBuilder _builder, HierarchicalNode node, string selectedKey, string baseImagePath)
        {
            if (node.IsAccessibleToUser())
            {
                var root = node.RootNode;
                string _bPath = baseImagePath.EndsWith("/") ? baseImagePath : baseImagePath + "/";
                string img = _bPath + "dash.gif";
                bool isLastNode = node.NextSibling == null;
                bool isRoot = node.Equals(root);
                if (!isRoot)
                {
                    if (isLastNode)
                        img = _bPath + "l.gif";
                }

                if (isRoot || isLastNode)
                    _builder.WriteBeginTag("li", new { style = "clear:left;padding-left:0px;min-height:20px;margin:0px 2px 0px 0;background:none;" });
                else
                    _builder.WriteBeginTag("li", new { style = "clear:left;padding-left:5px;min-height:20px;margin:0 2px 0 0;background-image:url('" + _bPath + "i.gif');background-repeat:repeat-y;" });

                if (!isRoot)
                {
                    //if (isRoot)
                    //    _builder.WriteBeginTag("div", new { style = "float:left;width:19px;height:20px;background:none;" });
                    //else
                        _builder.WriteBeginTag("div", new { style = "float:left;width:19px;height:20px;background-repeat:no-repeat;background-image:url(" + img + ");" });
                    _builder.WriteEndTag("div");
                }

                _builder.WriteBeginTag("a", new
                {
                    rel = node.Key,
                    href = "javascript:void(0);",
                    style = (node.Key == selectedKey) ? "padding:3px;" : "padding:3px;border-color:transparent;background:none;display:inline-block;",
                    Class = (node.Key == selectedKey) ? "ui-helper-reset ui-state-active" : "ui-helper-reset ui-state-default"
                });

                if (node.Key == "0")
                    _builder.Write("Root");
                else
                    _builder.Write(node.Title);
                _builder.WriteEndTag("a");
                if (node.HasChildNodes)
                    WriteNodesResursive(_builder, node.ChildNodes, selectedKey, baseImagePath);
                _builder.WriteEndTag("li");
            }
        }

        private static void WriteNodesResursive(NodeUIBuilder _builder, IEnumerable<HierarchicalNode> nodes, string selectedKey, string baseImagePath)
        {
            if (nodes != null)
            {
                _builder.WriteBeginTag("ul", new
                {
                    style = ((nodes.First().ParentNode == null) || (nodes.First().ParentNode.Key == "0")) ? "padding-left: 5px; " : "padding-left: 5px; margin-left: 20px;",
                    Class = "ui-helper-reset"
                });
                foreach (HierarchicalNode node in nodes)
                    WriteNodeRecursive(_builder, node, selectedKey, baseImagePath);
                _builder.WriteEndTag("ul");
            }
        }

        private static string GetTreeCore(string name, HierarchicalNode root, string selectedKey, string baseImagePath)
        {
            if (string.IsNullOrEmpty(baseImagePath))
                throw new ArgumentNullException("baseImagePath");
            var builder = new HierarchicalNodeUIBuilder();

            var nodeAttributes = new { Class = "ui-helper-reset", style = "padding-left:5px;" };
            var containerAttributes = new { style = "display:block;", Class = "ui-helper-reset" };
            builder.WriteBeginTag("ul", new { Class = "ui-helper-reset ui-widget-content ui-corner-bottom", style = "z-Index:3000;padding-left:5px;position: absolute;display:none;min-height:200px;min-width:150px;", id = name + "_tree" });
            WriteNodeRecursive(builder, root, selectedKey, baseImagePath);
            builder.WriteEndTag("ul");
            return builder.ToString();
        }

        public static MvcHtmlString DropDownTree(this AjaxHelper helper, string name, IHierarchicalNodeProvider provider, string selectedKey)
        {
            return helper.DropDownTree(name, provider, selectedKey, null, null);
        }

        public static MvcHtmlString DropDownTree(this AjaxHelper helper, string name, IHierarchicalNodeProvider provider, string selectedKey, TreeViewOptions options)
        {
            return helper.DropDownTree(name, provider, selectedKey, options, null);
        }

        public static MvcHtmlString DropDownTree(this AjaxHelper helper, string name, IHierarchicalNodeProvider provider, string selectedKey, TreeViewOptions options, object htmlAttributes)
        {
            TagBuilder _treeview = new TagBuilder("div");
            var opt = options != null ? options : new TreeViewOptions() { BaseImageUrl = "/images/" };
            string baseImagePath = opt.BaseImageUrl;
            HierarchicalNode selectedNode = selectedKey == "0" ? provider.RootNode : provider.FindNodeFormKey(selectedKey);

            if (string.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");
            TagBuilder _dropdown = new TagBuilder("div");
            string _id = name + "_dropdown";
            string _key = string.IsNullOrEmpty(selectedKey) ? "0" : selectedKey;

            if (htmlAttributes != null)
                _dropdown.MergeAttributes<string, object>(ObjectHelper.ConvertObjectToDictionary(htmlAttributes));
            if (_dropdown.Attributes.ContainsKey("style"))
                _dropdown.Attributes["style"] += "height:18px;padding:5px;position:relative;";
            else
                _dropdown.MergeAttribute("style", "height:18px;padding:5px;position:relative;");
            _dropdown.Attributes.Add("class", "ui-widget-content ui-state-default ui-corner-all");
            _dropdown.InnerHtml = "<input type='hidden' id='" + name + "' name='" + name + "' value='" + _key + "'>"; //value 
            _dropdown.InnerHtml += "<div style='float:left;display:block;' id='" + name + "_txt'>" + (selectedNode != null ? selectedNode.Title : "Root") + "</div>"; //text for selected
            _dropdown.InnerHtml += "<span style='float:right;' class=' ui-icon ui-icon-triangle-1-s'></span>";
            _dropdown.InnerHtml += GetTreeCore(name, provider.RootNode, selectedKey, !string.IsNullOrEmpty(baseImagePath) ? baseImagePath : "/images");
            _dropdown.Attributes.Add("id", _id);
            var scripts = new StringBuilder();
            scripts.Append("$('#" + _id + "').click(function(event){event.stopPropagation();$('#" + name + "_tree').slideToggle().position({ of: $('#" + _id + "'), my: 'left top', at:'left bottom'});});")
            .Append("$('#" + name + "_tree').find('a').click(function(event){")
            .Append("$('#" + name + "').val($(this).attr('rel'));")
            .Append("$('#" + name + "_txt').text($(this).text());");
            if (!string.IsNullOrEmpty(opt.OnNodeSelected))
                scripts.Append("try{" + opt.OnNodeSelected + "}catch(e){}");
            scripts.Append("$('#" + name + "_tree').find('.ui-state-active').removeClass('ui-state-active');")
            .Append("$(this).addClass('ui-state-active');")
            .Append("});");
            helper.RegisterStartupScript(scripts.ToString());
            return MvcHtmlString.Create(_dropdown.ToString());
        }

    }
}
